Skip to content

feat(types)!: retire ComponentInput.label / defaultValue / advanced as ADR-0049 tombstones (objectui#7493 item 1 / objectui#7781) - #7932

Merged
os-justin merged 9 commits into
mainfrom
claude/issue-7493-component-input-retire-dead-keys
Sep 6, 2026
Merged

feat(types)!: retire ComponentInput.label / defaultValue / advanced as ADR-0049 tombstones (objectui#7493 item 1 / objectui#7781)#7932
os-justin merged 9 commits into
mainfrom
claude/issue-7493-component-input-retire-dead-keys

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Refs #7493 (item ①)
Fixes #7781

Item ① of objectui#7493 under the maintainer's ruling A: retire (record 5556358261, 2026-09-06T02:32Z; verbatim 「第二批(4 项,契约形状族) 帮我处理,全部同意」), with objectui#7781's two keys folded into the same stroke. Items ② (validateSchema(schema: any), domain:ui) and ③ (the governed skills guide line plus its KNOWN_BARE_ANY_EXAMPLES row) are not part of this PR; #7493 remains open for them. Dev subagent of the domain:spec @ objectui PM seat, PM session session_01BAZFhALsQsGqxui8sNqM8s; identity is the branch. Contract review: needs:contract-review (a published @object-ui/types accept set narrows on both faces). Placeholders below are spelled as words, never as bracket-shaped tokens, because the body sanitizer eats those.

Premise, re-verified on origin/main 6a9ee323 (the cut; the seat's fa7d66c4 had advanced by PR #7889)

  • packages/types/src/base.ts:528 export interface ComponentInput { with label at :603, defaultValue at :608, advanced at :628 (the like-named members at :51, :140, :732 belong to other interfaces and are untouched).
  • packages/types/src/zod/base.zod.ts:301 export const ComponentInputSchema = z.object({ with label at :320, defaultValue at :321, advanced at :331 (:326 is the nested enum-option object's own label, untouched).
  • Parity rows zod-mirror-parity.test.ts:577 / :739: NOT touched by this PR — the tombstone route keeps every pair, so no ledger figure moves (the sibling Decision: ObjectViewSchema's ten unmirrored declared keys are LOCAL (objectui#7279 re-derivation) — mirror them, retire them, or defer to #2231? #7779's regions in that file are untouched too).
  • Item ② packages/core/src/validation/schema-validator.ts:458 and item ③ skills/objectui/guides/plugin-development.md:103 / scripts/check-skill-examples.mjs:558: read-only, not touched.

The route was MEASURED before it was chosen — tombstone

On the BUILT face (packages/types/dist/zod/index.zod.js at the base; pnpm --filter @object-ui/types build exit 0): ComponentInputSchema.safeParse({ name: 'content', type: 'string', notAKeyAtAll: 'anything' }) returns success: true with the key ABSENT from data — an undeclared key is silently STRIPPED, not refused; the schema's def carries no catchall and no strict flag. Control on the same call: the objectui#5905 tombstone min: 1 returns success: false, code: 'invalid_type', path: ['min'], message beginning RETIRED (objectui#5905). Deletion would therefore have swallowed 1,162 authored values in silence, and the route is forced: ?: never on the interface plus retirementTombstone() on the mirror — the PR #7761 / #7769 / #7832 shape, and exactly what objectui#5905 did for its five keys (PR #7639's commit body: "Deleting the member outright stays the option NOT taken: ComponentInputSchema is a non-strict z.object, so an undeclared key is silently stripped"). Followed. The deletion-with-absence-pin route of PR #7743 / #7832 does not apply here.

The census, re-derived with controls — the stop condition did not fire

Readers. Every non-test access of .inputs under packages/** and apps/** enumerated on the tree: sdui-parser/src/index.ts:153 (the serializer; forwards name, type, required, enum, binding, description), codegen.ts:76 / :151 / :152 and validate.ts:55 / :58 (the manifest shape — the boundary type RegistryConfigLike.inputs at index.ts:70-84 has no slot for the three), core/src/registry/Registry.ts:392-394 (input?.name only), components/src/renderers/layout/page.tsx:464 (forwards meta?.inputs into the serializer), core/src/registry/WidgetRegistry.ts:175 (a WRITE). Receiver-shaped reads of .label / .defaultValue / .advanced on an input outside tests: exactly the three WidgetRegistry copy lines (:178, :179, :183) — writes, not reads. Zero production readers; the ruling's premise holds.

Authorship. Depth-1 bracket-balanced scan over every inputs: [ array in tracked .ts/.tsx/.js/.jsx/.mjs/.cjs files (the instrument of report 5553590885): 121 files, 203 arrays, 952 input objects — label 908, defaultValue 245, advanced 9; controls in the same pass over the same regions name 951, type 951 (description 193, enum 119, required 86, binding 4). Identical to the report's reading. A WIDER instrument that also walks the three standalone ComponentInput[] = [ arrays (containers.tsx PAGE_CONTAINER_INPUTS, plugin-detail CHATTER_INPUTS, plugin-grid GRID_QUERY_INPUTS): 985 objects — label 941, defaultValue 247, advanced 9; controls name 984, type 984. Neither instrument sees a bare named array (plugin-tree's treeInputs) or a typed record (html-elements.tsx's PER_TAG_INPUTS); tsc found those two, which is what the tombstone is for. After the deletions the wide instrument reads label 0 / defaultValue 0 / advanced 0 with name 984 / type 984 unchanged, and the new pin carries that census as a tree-scoped test.

What moves

  1. Both faces. base.ts: label?: never, defaultValue?: never, advanced?: never with the RETIRED docblocks (what each was, the census — zero readers, the serializer's six forwarded keys, the authorship counts — and what an author writes instead: nothing; the input's name, the renderer's own fallback read, and description for telling an author about a default). base.zod.ts: three retirementTombstone() members, one guidance string each feeding both the parse-time message and .describe().
  2. Every authoring site. 1,199 keys deleted across 110 files by the census's own instrument (per-file table at the end), plus PER_TAG_INPUTS (14 label), treeInputs (2 label), ELEMENT_DATA_SOURCE_INPUT's label (packages/core/src/data-scope/element-data-source.ts, its type and its object), and the WidgetRegistry seam copy (three lines; WidgetInput keeps its own members). No as any, no cast, no rename anywhere: the values are deleted because nothing reads them. Three comments that described a deleted defaultValue were rewritten (text.tsx, text-input.tsx, plugin-detail/index.tsx).
  3. The nine test files that read defaultValue — re-pinned against the renderer's ACTUAL default; table below.
  4. Ledger — untouched (see premise).
  5. New pin packages/types/src/__tests__/component-input-retired-keys-7493.test.ts (23 tests): both faces refuse each key at path with the guidance (invalid_type, message equals .describe(), the remedy named per key), through the ComponentMetaSchema door at inputs.0.label too; @ts-expect-error legs at a real registration shape (and the registration's own ComponentMeta.label shown live); controls — the five declared forwarded keys accepted with their values kept AND value-enforced (wrong-typed name / type / required / enum / description refused at their own path; binding is objectui#6950's, undeclared on this face); the undeclared-key strip contrast (the route measurement, restated); an interface census read off base.ts (exactly eight ?: never tombstones, exactly the five live keys) and the mirror agreeing member for member; the serializer's forward set read off sdui-parser/src/index.ts (exactly six); a tree-scoped absence census over every inputs: [ and ComponentInput[] = [ array under packages/STAR/src and apps/STAR/src with name / type floors as controls (skips only this pin and its sibling pin, reason stated in the file).
  6. Existing pin component-input-retired-constraint-keys.test.ts: LIVE_INPUT stops authoring label (it is a tombstone now); nothing else moves.
  7. Docs. content/docs/guide/architecture.md, component-registry.md, plugin-development.md fences stop authoring the keys (a default moves into description); the plugin-development prose no longer says the designer reads ComponentInput entries (it never did) and names the six forwarded keys. content/docs/releases/ untouched.
  8. packages/types/src/widget.ts docblock: a third divergence recorded — WidgetInput.label / defaultValue / advanced stay declared and writable on the widget-manifest face, and are now measured reader-less (filed as [finding] WidgetInput.label / defaultValue / advanced (packages/types/src/widget.ts) have no reader once WidgetRegistry stops copying them onto the retired ComponentInput keys — #7781's class, one face over #7911, no ruling implied).
  9. Changeset .changeset/7493-componentinput-retire-label-defaultvalue-advanced.md: @object-ui/types: minor, opening "Breaking for authored metadata:", the FROM → TO per key, the route measurement, the accept-set change in words, the migration (delete the key); patch entries for the 24 packages whose registrations stopped authoring the keys.

The nine defaultValue-reading test files

file disposition
apps/console/src/__tests__/public-block-binding-reach.test.tsx the sampler's declared-default branch deleted (it was dead); every generic sample still reaches — green unchanged
apps/console/src/__tests__/record-block-record-reach.test.tsx same deletion; the six renderer defaults the sampler used to read off the declaration are restated in its own SAMPLE_BY_INPUT table beside the read each mirrors (relationshipValueField || 'id', showHeader ?? false, location || 'record_header', align || 'end', variant || 'default', size || 'sm') — measured: with the generic type samples three blocks stopped reaching (3 red), with the restated defaults 29 / 29 green
packages/components/src/__tests__/icon-renderer-declared-default.test.ts the coupling half (palette glyph equals the input's default) retired with the key; the file STAYS because scripts/__tests__/check-lucide-icon-record-names.test.ts:1036 requires it as the objectui#5936 record, and now pins the one remaining declared spelling (meta.icon is a non-empty string) plus the input's absent default. No renderer default exists to re-pin against: an absent icon name renders the placeholder branch by design (objectui#5631)
packages/components/src/__tests__/record-picker-inputs-spec-parity.test.ts the shadow-default absence assertion dropped (it only restated the declaration); the spec half — a parse carries no filter — kept and the case renamed
packages/components/src/__tests__/text-input-inputs-spec-parity.test.ts same as the row above, for the defaultValue entry's own default
packages/layout/src/__tests__/appSchemaRendererMobileNavMode.test.tsx re-pinned against AppSchemaRenderer.tsx's destructuring default (mobileNavMode = 'drawer', read off disk) and the description's "drawer" (default)
packages/plugin-detail/src/__tests__/recordDetailsInputs.spec-parity.test.ts re-pinned against record-details.tsx's own reads schema.inlineEdit ?? true and schema.showHeader ?? false (read off disk); the description regexes kept
packages/plugin-detail/src/__tests__/recordRelatedListInputs.spec-parity.test.ts re-pinned against record-related-list.tsx's relationshipValueField || 'id' (read off disk) and the description's Defaults to "id"; the spec-parse fallback assertion kept
packages/plugin-editor/src/index.test.ts the defaultValue assertion deleted; defaultProps.readOnly === false — the renderer's actual default — was already pinned four lines above

Gates — final head b64d033bc, exit codes captured before any pipe, heavy runs under the shared verify lock

  • pnpm --filter @object-ui/types build: exit 0 (dist completeness: 1 package(s) complete (124 emitted files verified)).
  • pnpm --filter @object-ui/types type-check (tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json, script name echoed): exit 0.
  • pnpm exec vitest run --maxWorkers=2 over component-input-retired-keys-7493, component-input-retired-constraint-keys, zod-mirror-parity: Test Files 3 passed (3) · Tests 55 passed (55) — the parity verdict is green with no ledger movement.
  • Consumer closure builds, DOWNSTREAM direction (turbo run build --concurrency=2, each package's build is its tsc / typed vite build): components' dependency closure 7 / 7; components + layout + fields + sdui-parser 11 / 11; ten plugins 23 / 23; the remaining plugins + app-shell 30 / 30; cli + map + markdown + timeline 17 / 17; after the merge app-shell + timeline 30 / 30 — every call VERDICT command-exit 0. The two RED intermediate readings were real finds (html-elements.tsx PER_TAG_INPUTS, plugin-tree treeInputs), fixed and rebuilt.
  • type-check (tsc --noEmit && tsc -p tsconfig.test.json, tests included) on core, components, layout, plugin-tree, plugin-editor, plugin-detail, the sixteen other plugins, app-shell and console (tsc --noEmit && tsc -b tsconfig.node.json): every one exit 0 with its script name echoed (one RED reading — a duplicate import the re-pin introduced — fixed in its own commit and re-read green).
  • pnpm exec vitest run --maxWorkers=2 packages/core/ packages/layout/ packages/plugin-detail/ packages/plugin-editor/ packages/plugin-tree/ + the two console reach files: first run Test Files 1 failed | 281 passed (282) · Tests 3 failed | 3987 passed (3990) (the record-reach probe, see the table); the two reach files re-run Test Files 2 passed (2) · Tests 29 passed (29).
  • pnpm exec vitest run --maxWorkers=2 packages/components/: Test Files 233 passed (233) · Tests 2149 passed (2149).
  • Lint, a DECLARED narrowing: pnpm exec eslint over the 125 changed code files (the root eslint.config.js is the repository's only eslint config, so an untouched file's verdict cannot move): exit 0, 0 errors, 715 warnings (pre-existing no-explicit-any warnings). The per-package pnpm lint farm is CI's.
  • node scripts/check-changeset-presence.mjs: exit 0 (126 source file(s) of 25 released package(s) changed, and this change declares 1 changeset(s)); check-changeset-fixed / -overwrite / -no-major: exit 0 each.
  • node scripts/check-control-bytes.mjs: exit 0 (scanned 6402 tracked text file(s)); self-scan grep -naP over every changed file: no hit.
  • pnpm check:spec-symbols exit 0 · pnpm check:doc-fences exit 0 · pnpm check:doc-types exit 0 (Every documented component type is registered).
  • node scripts/check-doc-snippet-types.mjs on the fully built tree: exit 0 (456 of 456 block(s) judged, 0 failed).
  • node scripts/check-skill-examples.mjs (item ③'s surface, read only): exit 0 — 13 of 13 ts fence(s) judged, 0 failed; Bare any: 1 finding(s) … 1 declared in KNOWN_BARE_ANY_EXAMPLES … 0 declared row(s) no longer red — the baseline row is NOT stale, because the guide still carries defaultValue?: any.
  • Governed-surface predicate (objectstack scripts/pm/check-governed-merges.mjs --test, the final 130-path list): 0 of 130 path(s) hit the register … NOT governed.
  • Not run locally, CI's: pnpm test over the other downstream packages and the per-package pnpm lint farm.

Ablation (Clause-② yes) — predicted in writing before the run

One script under the verify lock, trap restore EXIT INT TERM, absolute paths from git rev-parse --show-toplevel, the implementation committed first. Mutation: the zod face alone back to the pinned base (git checkout 6a9ee323 -- packages/types/src/zod/base.zod.ts); on-disk proof: marker RETIRED (objectui#7493) count 3 → 0, old spelling defaultValue: z.any().optional() count 1, git hash-object equals the base blob ec957d27…; types dist rebuilt under mutation (exit 0), marker count in dist/zod/base.zod.js 0. Prediction: the zod-face cases go RED — the three per-key refusals, the nested registration door, the literal defaultValue string, "the three stay in the mirror's shape", the mirror-agrees census (seven) — while the tsc legs, the forwarded-key controls (accepted and the five value-enforced), the undeclared-key strip contrast, the interface census, the serializer read and the tree census stay GREEN (sixteen). Observed: Tests 7 failed | 16 passed (23), exactly those seven. Restore: git checkout HEAD -- ABSOLUTE_PATH; git hash-object equals the HEAD blob 651b1037… (IDENTICAL), git diff HEAD -- path EMPTY, git status clean for the file; dist rebuilt (exit 0), marker back to 3; the pin Tests 23 passed (23).

Overlaps and readings the seat needs

Per-file deletions (110 files, 1,199 keys; the instrument's own count, PER_TAG_INPUTS / ELEMENT_DATA_SOURCE_INPUT / the WidgetRegistry copy not included)

file keys deleted
packages/plugin-detail/src/index.tsx 126
packages/plugin-chatbot/src/renderer.tsx 96
packages/plugin-form/src/index.tsx 70
packages/plugin-dashboard/src/index.tsx 63
packages/plugin-designer/src/index.tsx 57
packages/plugin-view/src/index.tsx 36
packages/components/src/renderers/layout/containers.tsx 33
packages/plugin-grid/src/index.tsx 29
packages/plugin-ai/src/index.tsx 24
packages/components/src/renderers/basic/elements.tsx 23
packages/components/src/renderers/complex/data-table.tsx 22
packages/plugin-charts/src/index.tsx 21
packages/components/src/renderers/form/input.tsx 20
packages/components/src/renderers/form/form.tsx 20
packages/plugin-kanban/src/index.tsx 18
packages/plugin-calendar/src/calendar-view-renderer.tsx 17
packages/components/src/renderers/navigation/sidebar.tsx 15
packages/plugin-list/src/index.tsx 14
packages/components/src/renderers/action/action-button.tsx 13
packages/components/src/renderers/action/action-bar.tsx 13
packages/plugin-timeline/src/renderer.tsx 12
packages/components/src/renderers/basic/data-list.tsx 12
packages/components/src/renderers/action/action-group.tsx 12
packages/components/src/renderers/overlay/sheet.tsx 11
packages/components/src/renderers/layout/flex.tsx 11
packages/plugin-editor/src/index.tsx 10
packages/components/src/renderers/overlay/alert-dialog.tsx 10
packages/components/src/renderers/action/action-icon.tsx 10
packages/components/src/renderers/overlay/drawer.tsx 9
packages/components/src/renderers/overlay/dialog.tsx 9
packages/components/src/renderers/layout/stack.tsx 9
packages/components/src/renderers/layout/grid.tsx 9
packages/components/src/renderers/form/slider.tsx 9
packages/components/src/renderers/basic/record-picker.tsx 9
packages/components/src/renderers/overlay/tooltip.tsx 8
packages/components/src/renderers/layout/page.tsx 8
packages/components/src/renderers/form/button.tsx 8
packages/components/src/renderers/basic/text-input.tsx 8
packages/plugin-report/src/index.tsx 7
packages/components/src/renderers/overlay/popover.tsx 7
packages/components/src/renderers/overlay/hover-card.tsx 7
packages/components/src/renderers/layout/container.tsx 7
packages/components/src/renderers/form/toggle.tsx 7
packages/components/src/renderers/feedback/toast.tsx 7
packages/components/src/renderers/disclosure/toggle-group.tsx 7
packages/components/src/renderers/complex/resizable.tsx 7
packages/components/src/renderers/complex/carousel.tsx 7
packages/components/src/renderers/action/action-menu.tsx 7
packages/layout/src/index.ts 6
packages/components/src/renderers/overlay/dropdown-menu.tsx 6
packages/components/src/renderers/form/textarea.tsx 6
packages/components/src/renderers/form/select.tsx 6
packages/components/src/renderers/form/radio-group.tsx 6
packages/components/src/renderers/feedback/sonner.tsx 6
packages/components/src/renderers/feedback/loading.tsx 6
packages/plugin-charts/src/ObjectChart.tsx 5
packages/components/src/renderers/layout/aspect-ratio.tsx 5
packages/components/src/renderers/form/file-upload.tsx 5
packages/components/src/renderers/form/combobox.tsx 5
packages/components/src/renderers/form/checkbox.tsx 5
packages/components/src/renderers/disclosure/collapsible.tsx 5
packages/components/src/renderers/disclosure/accordion.tsx 5
packages/components/src/renderers/data-display/list.tsx 5
packages/components/src/renderers/data-display/avatar.tsx 5
packages/components/src/renderers/data-display/alert.tsx 5
packages/components/src/renderers/complex/table.tsx 5
packages/components/src/renderers/complex/scroll-area.tsx 5
packages/components/src/renderers/basic/pagination.tsx 5
packages/components/src/renderers/basic/icon.tsx 5
packages/components/src/renderers/basic/button-group.tsx 5
packages/plugin-timeline/src/index.tsx 4
packages/plugin-map/src/index.tsx 4
packages/plugin-gantt/src/index.tsx 4
packages/plugin-calendar/src/index.tsx 4
packages/components/src/renderers/overlay/context-menu.tsx 4
packages/components/src/renderers/navigation/header-bar.tsx 4
packages/components/src/renderers/form/date-picker.tsx 4
packages/components/src/renderers/feedback/empty.tsx 4
packages/components/src/renderers/data-display/statistic.tsx 4
packages/components/src/renderers/data-display/badge.tsx 4
packages/components/src/renderers/complex/filter-builder.tsx 4
packages/components/src/renderers/basic/text.tsx 4
packages/components/src/renderers/layout/tabs.tsx 3
packages/components/src/renderers/layout/card.tsx 3
packages/components/src/renderers/form/switch.tsx 3
packages/components/src/renderers/form/input-otp.tsx 3
packages/components/src/renderers/form/command.tsx 3
packages/components/src/renderers/form/calendar.tsx 3
packages/components/src/renderers/feedback/toaster.tsx 3
packages/components/src/renderers/feedback/spinner.tsx 3
packages/components/src/renderers/feedback/skeleton.tsx 3
packages/components/src/renderers/feedback/progress.tsx 3
packages/components/src/renderers/data-display/tree-view.tsx 3
packages/components/src/renderers/data-display/breadcrumb.tsx 3
packages/components/src/renderers/basic/separator.tsx 3
packages/components/src/renderers/basic/image.tsx 3
packages/plugin-tree/src/index.tsx 2
packages/plugin-markdown/src/index.tsx 2
packages/components/src/renderers/form/label.tsx 2
packages/components/src/renderers/data-display/kbd.tsx 2
packages/components/src/renderers/overlay/menubar.tsx 1
packages/components/src/renderers/layout/semantic.tsx 1
packages/components/src/renderers/layout/box.tsx 1
packages/components/src/renderers/basic/span.tsx 1
packages/components/src/renderers/basic/navigation-menu.tsx 1
packages/components/src/renderers/basic/html.tsx 1
packages/components/src/renderers/basic/html-elements.tsx 1
packages/components/src/renderers/basic/div.tsx 1
packages/app-shell/src/views/record-attachments-renderer.tsx 1
packages/app-shell/src/views/record-approvals-renderer.tsx 1

🤖 Generated with Claude Code

https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s


Generated by Claude Code

…s ADR-0049 tombstones (objectui#7493 item 1, objectui#7781)

The three ComponentInput keys the manifest serializer does not forward, and
that nothing reads on any publication or consumption path, are retired on
both faces under the maintainer's ruling A of 2026-09-06.

Route measured on the built face before editing: ComponentInputSchema is a
non-strict z.object, so an undeclared key parses green and is silently
stripped -- a deletion would have swallowed 1,162 authored values in silence.
So each key stays declared and refuses BY NAME: `?: never` on the interface
and retirementTombstone() on the Zod mirror (the objectui#5905 shape).

- base.ts / base.zod.ts: three tombstones with the RETIRED docblocks (the
  census, the serializer's six forwarded keys, the authorship counts, what to
  write instead: nothing)
- every in-repo authoring site deleted: 1,197 keys across 109 registration
  files (the 908 / 245 / 9 the inputs-literal census counted, plus the three
  standalone ComponentInput[] arrays), html-elements' PER_TAG_INPUTS record,
  ELEMENT_DATA_SOURCE_INPUT's label, and the WidgetRegistry seam copy (the one
  non-test write, which fed nothing)
- the nine defaultValue-reading tests re-pinned against the renderer's ACTUAL
  default (its own fallback read or defaultProps); two shadow-default
  assertions dropped with the reason on the line; the icon coupling pin keeps
  its one remaining declared spelling
- new pin component-input-retired-keys-7493: both faces refuse at path with
  the guidance, tsc legs at a real registration shape, forwarded-key controls
  (accepted and value-enforced), serializer forward set read off disk, an
  eight-tombstone census of the interface on both faces, and a tree-scoped
  absence census over every inputs array under packages/ and apps/
- widget.ts records the third divergence (WidgetInput keeps its three,
  measured reader-less now: objectui#7911); four docs guides stop authoring
  the keys; changeset (types minor, "Breaking for authored metadata", patch
  entries for the registration cleanups)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
…` too

`tsc` found the one registration array the inputs-literal census could not
see: `treeInputs` is a bare const referenced from two registrations. Its two
`label` writes go the way of the other 1,197; the changeset totals and its
patch list follow.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
…nc once

The re-pin added a second `readFileSync` import beside the one the file
already carried; `tsc -p tsconfig.test.json` refused the duplicate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
…lts it used to read off `defaultValue`

`sampleFor` seeded `relationshipValueField`, `showHeader`, `location`,
`align`, `variant` and `size` from the registrations' declared defaults, which
happened to be the renderers' own fallbacks and the one configuration under
which the probe is askable. With `ComponentInput.defaultValue` retired the
generic type samples took over — `'x'` for a parent field, the header chrome
on, a location with no actions — and three blocks stopped reaching. The six
values now sit in SAMPLE_BY_INPUT beside the read each mirrors.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3183.9 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-DLJj0aZA.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 497.42KB 113.96KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 47.35KB 13.21KB
plugin-charts (index.js) 70.31KB 19.62KB
plugin-chatbot (index.js) 193.53KB 46.05KB
plugin-dashboard (index.js) 131.41KB 34.43KB
plugin-designer (index.js) 211.51KB 43.01KB
plugin-detail (index.js) 247.59KB 63.48KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.56KB 56.63KB
plugin-kanban (index.js) 52.30KB 14.49KB
plugin-list (index.js) 113.24KB 27.66KB
plugin-map (index.js) 20.35KB 6.77KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 29.95KB 8.67KB
plugin-tree (index.js) 9.16KB 3.18KB
plugin-view (index.js) 84.33KB 20.75KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Copy link
Copy Markdown
Contributor

Contract review (clause ②) — PASS on content; landing on green — PR #7932 at head b64d033b (Refs #7493 item ①, Fixes #7781)

Director seat (objectstack #12708, summon #15), session_01TezFG8ZMrNH6n5VTNpPpdH (os-zhuang), 2026-09-06T03:43Z, batch review under the maintainer's 「按批次执行完所有的契约复审」. Tier fuse: get_session this session reads session_context.model = last_served_model = CONTRACT_REVIEW_TIER. Readings from the PR diff — the contract files in full (packages/types/src/base.ts, zod/base.zod.ts, widget.ts, core/src/registry/WidgetRegistry.ts, core/src/data-scope/element-data-source.ts), a sampled registration file (renderers/basic/text-input.tsx), the changeset, the 130-file list — plus cards #7781 (ruling 5556358745) and #7493's ruling record (A: retire, 2026-09-06, 「第二批(4 项,契约形状族) 帮我处理,全部同意」).

Implemented-by: dev subagent of session_01BAZFhALsQsGqxui8sNqM8s (branch claude/issue-7493-component-input-retire-dead-keys)
Reviewed-by: session_01TezFG8ZMrNH6n5VTNpPpdH

Clause ② standing — yes, correctly declared

ComponentInput.label / defaultValue / advanced become ?: never on the TS face and retirementTombstone() members on ComponentInputSchema: a document authoring any of the three parsed green (value silently stripped) and now parses red at the key. Published @object-ui/types accept set narrows on both faces.

① Derived judgments

# claim reading verdict
1 Route measured before chosen: ComponentInputSchema is a non-strict z.object, an undeclared key is silently stripped on the built face (control: the objectui#5905 tombstone min refuses) ⇒ deletion would trade one silent no-op for another; tombstone on both faces, the objectui#5905 / PR #7639 shape Diff read: three retirementTombstone() members with one guidance string each; ?: never with the RETIRED docblocks carrying census, ruling and remedy. correct
2 Reader census: every non-test consumer of ComponentMeta.inputs enumerated; the serializer forwards exactly six keys; the only non-test touch of the three was WidgetRegistry's write, now deleted WidgetRegistry.ts hunk drops the three copies and says why; WidgetInput keeps its own members (widget-manifest face, unruled) — recorded in widget.ts as divergence 3 and filed as #7911. correct
3 Authorship census with controls (name 951 / type 951): label 908, defaultValue 245, advanced 9; 1,199 keys deleted across 110 files plus the standalone arrays and the two named arrays tsc found; post-deletion census 0/0/0 with controls unchanged, carried as a tree-scoped pin Sampled registration confirms the shape (only label: / defaultValue: lines removed; one comment rewritten). The two RED intermediate consumer builds were real finds, fixed. correct
4 Nine defaultValue-reading test files re-pinned against the renderer's actual default (own fallback read or defaultProps), two shadow-restating assertions dropped with the reason on the line Table read; the right direction — a pin on a declaration nothing reads was never coverage. correct
5 New 23-test pin: both faces refuse at path with guidance, through the ComponentMetaSchema door too; forwarded-key controls value-enforced; the strip contrast restated; interface/mirror census (eight tombstones, five live keys); serializer forward set read off disk; tree-scoped absence census Ablation 7 red / 16 green exactly as predicted. correct
6 Docs: three guide fences stop authoring the keys; content/docs/releases/ untouched; item ③ (skills/**, governed) read-only and correctly left for its own PR Governed surface not ridden. correct

② semver

@object-ui/types minor ("Breaking for authored metadata", fixed-group convention) plus patch on the 24 packages whose registrations stop authoring inert keys. Correct.

③ Boundary flags

Evidence and landing

Checks on b64d033b: 23 success / 3 skipped / 6 in progress (Type Check, four test shards, Build Docs); mergeable_state: behind (a main merge the queue performs, not a conflict); governed-surface predicate 0 of 130 paths. Clearing, same stroke: needs:contract-review off PR #7932 with provenance (the cards carry none). Landing (ready + auto-merge SQUASH) from this seat once every check is green — at its next check-in if the seat has not.


Generated by Claude Code

Copy link
Copy Markdown
Contributor

CI read at b64d033b — one red, the PR's own; patch round routed

Director seat, session_01TezFG8ZMrNH6n5VTNpPpdH, 2026-09-06T03:47Z. Test (shard 4/4) (job 101422144206) fails exactly one test, quoted from the log:

FAIL packages/plugin-kanban/src/index.test.ts > Plugin Kanban > kanban component > should have onCardMove as code input
AssertionError: expected undefined to be true
  packages/plugin-kanban/src/index.test.ts:62:41
      expect(onCardMoveInput?.advanced).toBe(true);
Test Files 1 failed | 641 passed (642) · Tests 1 failed | 7590 passed (7591)

A pin reading the retired advanced key off a registration — the census covered the nine defaultValue-reading test files but this advanced reader was not in that set. The key is now a tombstone and plugin-kanban/src/index.tsx no longer authors it (18 keys deleted there), so the assertion is asserting a value that can no longer exist. Patch round to the dispatching seat (session_01BAZFhALsQsGqxui8sNqM8s / os-justin): drop the advanced assertion (the toBeDefined / type === 'code' / description lines beside it stay), and sweep the tree for any other test reading .advanced or .label off an input so the same class does not surface shard by shard. Content PASS 5556699068 stands; a test-only head is extended, not re-reviewed. Landing on green.


Generated by Claude Code

… retires

`packages/plugin-kanban/src/index.test.ts` was not in this PR's diff, so its
`expect(onCardMoveInput?.advanced).toBe(true)` survived while
`plugin-kanban/src/index.tsx` stopped authoring `advanced` — a live CI red
(`Test (shard 4/4)`: `AssertionError: expected undefined to be true` at
`index.test.ts:62:41`). `tsc` cannot catch it: `expect(x).toBe(true)` accepts a
`never | undefined` receiver, so only running the suite finds it.

The three sibling assertions beside it stay — `toBeDefined()`, `type === 'code'`
and `description` all read live keys.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3185.9 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-CLDKM-TD.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 497.42KB 113.96KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 47.35KB 13.21KB
plugin-charts (index.js) 70.31KB 19.62KB
plugin-chatbot (index.js) 193.53KB 46.05KB
plugin-dashboard (index.js) 131.41KB 34.43KB
plugin-designer (index.js) 211.51KB 43.01KB
plugin-detail (index.js) 247.59KB 63.48KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.56KB 56.63KB
plugin-kanban (index.js) 52.30KB 14.49KB
plugin-list (index.js) 113.24KB 27.66KB
plugin-map (index.js) 20.35KB 6.77KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 29.95KB 8.67KB
plugin-tree (index.js) 9.16KB 3.18KB
plugin-view (index.js) 84.33KB 20.75KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Copy link
Copy Markdown
Collaborator Author

Seat note — the Gates section's anchor is stale; here is the current one. Posted as a comment rather than a body edit so the reserving seat's review target does not move under it.

The body reads "final head b64d033bc". The head is now 674bc3f55: one commit 86dce29c6 plus a merge of origin/main 0adb32982. Nothing in the body's gate readings is retracted — they were taken on b64d033bc and still hold — but they were not taken on what CI is running now, so the patch round re-measured on the pushed head.

Why there was a patch round. Test (shard 4/4) (job 101422144206) was red on b64d033bc, at packages/plugin-kanban/src/index.test.ts:62expect(onCardMoveInput?.advanced).toBe(true), AssertionError: expected undefined to be true. That line is a reader of advanced, one of the three ComponentInput keys this PR retires, and it is not in this PR's diff (git diff --name-only origin/main...<branch> -- packages/plugin-kanban/src/index.test.ts is empty), so the retirement made a file it never touched fail. It is also the one site #7781's census missed: that card asserts "Test files: zero reads of .label or .advanced on an input receiver", and the assertion propagated unchallenged into this PR's dispatch. The production half of that census was sound; the test half was never re-derived with the same instrument. That is the seat's defect, not the dev's, and it is recorded as such.

The patch is one deletion, no insertions, one file — the assertion line only. Its three siblings on the same receiver (toBeDefined(), type === 'code', description) are untouched; they read live keys. No schema, type, tombstone, docblock or accept-set moved in this round.

The bound was re-measured, not assumed. A receiver-shaped sweep over *.test.ts(x) / *.spec.ts(x) under packages/ and apps/ returns two hits: this site, and packages/i18n/src/__tests__/appDesigner-fieldDesigner-formula-retired-6310.test.ts:114, which is the quoted i18n key string 'appDesigner.fieldDesigner.typeCategory.advanced' inside a TYPE_CATEGORY array — not a property read. A cross-check shaped for all three retired keys returns 21 hits, of which this was the only executable receiver-shaped read; the rest are comments or quoted strings (the element:text_input.defaultValue / .label specimen test names in apps/console are live component props). Worth recording for anyone repeating the sweep: the first attempt's character class was written [A-Za-z0-9_)\]], where the backslash is literal inside a POSIX bracket expression, so the class closed early and the pattern returned a confident zero on the very site it was standing on. The corrected form puts ] first and was validated against a positive control before being trusted.

Re-runs on 674bc3f55, after pnpm install, exit captured before any pipe:

  • pnpm exec vitest run --maxWorkers=2 packages/plugin-kanban/ — exit 0, Test Files 23 passed (23), Tests 120 passed (120). Before the fix, at b64d033bc: exit 1, Tests 1 failed | 119 passed (120) — the CI red reproduced exactly, then closed.
  • pnpm --filter @object-ui/types build — exit 0, dist completeness: 1 package(s) complete (124 emitted files verified)
  • pnpm --filter @object-ui/types type-check — exit 0, script name echoed (so it ran rather than matching zero scripts)
  • node scripts/check-changeset-presence.mjs — exit 0

The full farm was not re-run locally; that is CI's, currently in progress on this head.

PR state untouched by the round: still draft, needs:contract-review absent and not re-attached, no ready flip, no enqueue, no auto-merge, no body edit. The push was a fast-forward b64d033bc..674bc3f55 — no force, no rebase. Landing stays reserved by the seat that reserved it.

One field to disregard: the API still reports mergeable_state: behind while base.sha already equals the 0adb32982 that was merged — it reads as not-yet-recomputed rather than real divergence.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Still red on 674bc3f55, for a different reason — do not land this head. Read at 04:19Z: every check green except Test (shard 4/4) (job 101425501671), Test Files 1 failed | 642 passed (643), Tests 1 failed | 7680 passed (7681).

The new failure is a collision with main, not a regression in the patch:

packages/types/src/__tests__/object-view-unmirrored-keys-7779.test.ts:270
  it('the registration still exposes the three local literals as editable props')
  AssertionError: expected '/**\n * ObjectUI\n …' to contain
    "{ name: 'defaultViewType', type: 'enum', label: 'Default View Type', enum: [...] },"

That pin file did not exist on the base this branch merged. PR #7922 landed at 04:02:18Z as 5b5a5c3a3one minute after this branch merged origin/main 0adb32982. CI tests the merge result against the current base, so the run saw a main that already carried it. Its new pin hard-codes three packages/plugin-view/src/index.tsx registration lines with the label: key inside them (object-view-unmirrored-keys-7779.test.ts:113-117), and this PR retires ComponentInput.label and deletes that key from inputs: entries repo-wide, plugin-view among them.

So the pin asserts a fact this PR is the reason is no longer true. That makes it this PR's fix, in this PR: the three expected strings drop the label: '…', fragment and stay otherwise exact. The pin's intent — the three local literals are still registered as editable inputs — survives the retirement unchanged, so it is corrected, not loosened, not deleted.

Patch round 2 is dispatched with that scope plus three things the single visible failure does not bound: a controlled sweep for any other test that hard-codes an inputs: entry containing one of the three retired keys (one shard's red is not a census), and a re-derivation — not a hand-merge — of zod-mirror-parity.test.ts's header figures, which #7922 moved for its ObjectViewSchema rows and this PR moves for its ComponentInputSchema rows. The corrected pin must also be shown to still fail when the deleted label: is put back, so it is a pin and not a transcription.

The PR stays DRAFT, unqueued, and reserved as it was. Next comment will carry the green head or a needs_decision.


Generated by Claude Code

…tion lines (objectui#7779 pin)

`packages/types/src/__tests__/object-view-unmirrored-keys-7779.test.ts` landed on
`main` (PR #7922) one minute after this branch merged its base, so its
`REGISTRATION_TEXT` hard-codes three `plugin-view/src/index.tsx` registration
lines that still carry the `ComponentInput.label` key this PR retires. The pin
asserted a fact this change is the reason is no longer true.

Each expected string is copied off the registration source rather than composed
by hand: only the `label: '…', ` fragment is dropped, every other character is
the line as `packages/plugin-view/src/index.tsx` now reads. The assertion stays
an exact `toContain` over three entries — the pin's intent (the three local
literals are still registered as editable inputs) survives the retirement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3186.0 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-CpGW7jKI.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 497.42KB 113.96KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 47.35KB 13.21KB
plugin-charts (index.js) 70.31KB 19.62KB
plugin-chatbot (index.js) 193.53KB 46.05KB
plugin-dashboard (index.js) 131.41KB 34.43KB
plugin-designer (index.js) 211.51KB 43.01KB
plugin-detail (index.js) 247.59KB 63.48KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.56KB 56.63KB
plugin-kanban (index.js) 52.30KB 14.49KB
plugin-list (index.js) 113.24KB 27.66KB
plugin-map (index.js) 20.35KB 6.77KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 29.95KB 8.67KB
plugin-tree (index.js) 9.16KB 3.18KB
plugin-view (index.js) 84.33KB 20.75KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Copy link
Copy Markdown
Collaborator Author

GREEN on 9773ca75d — all 32 check runs, read individually at 04:46Z. Run 34011693601 and its siblings: 29 success, 3 skipped (dependabot, Test (coverage), Test (coverage shard …) — the coverage matrix is not scheduled on this event), 0 failures, 0 pending. The four shards are each confirmed by their own check-run read rather than by an aggregate: shard 1/4 job 101428527719 ✅, shard 2/4 101428527725 ✅, shard 3/4 101428527692 ✅, and shard 4/4 101428527800 ✅ — the job that carried both reds.

What round 2 changed: one file, 3 insertions / 3 deletions, plus a merge of origin/main f10e49f36 (clean, no textual conflict). REGISTRATION_TEXT's three expected strings drop only the label: '…', fragment, each copied off packages/plugin-view/src/index.tsx by a script that errors unless its grep matches exactly once. The assertion stays an exact toContain over a three-entry readonly string[] — not loosened, nothing deleted, no entry dropped.

The bound, not a guess. A sweep of the merged tree for the same collision shape — a registration entry pinned inside a quoted string — returns 17 hits on the primary pass and 23 on a superset pass over the 138 files that name a registration or renderer path as a string, plus a pass confirming no gate script pins registration text. Exactly one live site, the one fixed. Every other hit is a different key that happens to share a spelling: ComponentMeta.label (the registration's own top-level label, which this PR does not retire), i18next's defaultValue, a NamedListView label, an ActionDef, nav items, changelog prose — each disposed individually. The sweep was run before the fix so the known-bad site appears in its own output as a positive control; after round 1's grep whose character class closed early and returned a confident zero on the site it was standing on, an unvalidated zero is not a reading here.

The corrected pin was shown to still fail. Re-inserting label: 'Default Named View' into the defaultListView entry moves the file's blob hash d131f5aa…bc5a90b1… (the script exits 92 if it does not, so the ablation cannot pass as a no-op); the pin then fails on exactly its own assertion, one test of ninety, the other 89 green. Restore returns the blob to the HEAD hash with a byte-empty diff and a green control run.

One correction to my earlier comment on this PR. I said this PR moves zod-mirror-parity.test.ts's header figures alongside #7922's. It does not touch that file at all — two independent git diff --stat legs come back empty, and this PR's own body said so at open time: the tombstone route keeps every mirror pair, so declared and enforced stay equal and no ledger row moves. The figures were re-derived on the merged tree anyway, by a line-oriented parse deliberately not the file's own AST walk: 14 entries / 87 keys, 2/3 spec-derived, 12/84 local — agreeing with all four header spellings and with the objectui#7279 pin, which the verbose reporter shows as having run. No edit was owed there and none was made. The mistaken overlap claim was inherited from #7922's body and repeated by me without re-deriving it; the seat's serial-queue record is corrected.

PR is DRAFT, unqueued, no auto-merge, needs:contract-review not re-attached — landing stays with the seat that reserved it, and this comment is the green reading it was waiting on, not a request to hand it over.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Landed by this seat at 05:07Z, on the reviewing seat's own instruction — not an override. The contract review (5556699068) closed with: "Landing (ready + auto-merge SQUASH) from this seat once every check is green — at its next check-in if the seat has not." That makes the dispatching seat the first mover and the Director seat the fallback, so with green in hand the stroke was mine to make.

Preconditions re-read live immediately before, not carried from the green comment:

  • head 9773ca75d, unchanged since the 04:46Z reading — no push in between, so the green belongs to this tree
  • mergeable_state: clean
  • needs:contract-review absent from the label set, cleared by the reviewing seat with provenance
  • governed-surface predicate 0 of 130 path(s) hit the register → NOT governed
  • the two patch rounds since the content PASS are test-only, which that review pre-authorised in as many words: "a test-only head is extended, not re-reviewed" — round 1 deleted one assertion, round 2 corrected three pin strings and merged main. No schema, type, tombstone, docblock or accept-set moved in either.

Sequence: draft:falseenable_pr_auto_merge SQUASH → queue-ref probe by git, since the enable call echoes empty method / enabled at fields even when it worked. Probe at 05:08:00Z:

refs/heads/gh-readonly-queue/main/pr-7932-b313700937c959322f83f0329e73525a3b13375c

Queued third, behind #7960 and #7961 and ahead of #7958.

Two things follow this PR and are recorded so they are not lost when this shift ends:

The #7685 collision this PR's body predicted on packages/plugin-detail/src/index.tsx still stands for whichever of the two lands second: the union is #7685's description text with no label key. Merge queue arbitrates, ⛔ no hand-ordering.


Generated by Claude Code

Merged via the queue into main with commit c6198c2 Sep 6, 2026
34 checks passed
@os-justin
os-justin deleted the claude/issue-7493-component-input-retire-dead-keys branch September 6, 2026 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment